package com.ruoyi.system.service.impl;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bpodgursky.jbool_expressions.Expression;
import com.bpodgursky.jbool_expressions.parsers.ExprParser;
import com.bpodgursky.jbool_expressions.rules.RuleSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.HttpUtil;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.system.domain.DrugResolveTable;
import com.ruoyi.system.domain.DrugRuleResolve;
import com.ruoyi.system.domain.DrugVerify;
import com.ruoyi.system.domain.vo.MatchVo;
import com.ruoyi.system.domain.vo.VerifyVo;
import com.ruoyi.system.mapper.DrugResolveTableMapper;
import com.ruoyi.system.mapper.DrugRuleResolveMapper;
import com.ruoyi.system.service.IDrugVerifyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.ruoyi.system.mapper.DrugRuleMapper;
import com.ruoyi.system.domain.DrugRule;
import com.ruoyi.system.service.IDrugRuleService;

import javax.annotation.Resource;

/**
 * 药品规则Service业务层处理
 * 
 * @author wmb
 * @date 2020-07-28
 */
@Service
public class DrugRuleServiceImpl implements IDrugRuleService 
{
    @Autowired
    private DrugRuleMapper drugRuleMapper;

    @Resource
    private DrugRuleResolveMapper drugRuleResolveMapper;

    @Resource
    private DrugResolveTableMapper drugResolveTableMapper;


    @Resource
    private IDrugVerifyService drugVerifyService;

    @Value("${drug.match.ai.url}")
    private String aiMatchUrl;

    @Value("${drug.match.str.url}")
    private String strMatchUrl;
    /**
     * 查询药品规则
     * 
     * @param id 药品规则ID
     * @return 药品规则
     */
    @Override
    public DrugRule selectDrugRuleById(Long id)
    {
        return drugRuleMapper.selectDrugRuleById(id);
    }

    /**
     * 查询药品规则列表
     * 
     * @param drugRule 药品规则
     * @return 药品规则
     */
    @Override
    public List<DrugRule> selectDrugRuleList(DrugRule drugRule)
    {
        return drugRuleMapper.selectDrugRuleList(drugRule);
    }

    /**
     * 新增药品规则
     * 
     * @param drugRule 药品规则
     * @return 结果
     */
    @Override
    public int insertDrugRule(DrugRule drugRule)
    {
        drugRule.setCreateTime(DateUtils.getNowDate());
        return drugRuleMapper.insertDrugRule(drugRule);
    }

    /**
     * 修改药品规则
     * 
     * @param drugRule 药品规则
     * @return 结果
     */
    @Override
    public int updateDrugRule(DrugRule drugRule)
    {
        return drugRuleMapper.updateDrugRule(drugRule);
    }

    /**
     * 批量删除药品规则
     * 
     * @param ids 需要删除的药品规则ID
     * @return 结果
     */
    @Override
    public int deleteDrugRuleByIds(Long[] ids)
    {
        return drugRuleMapper.deleteDrugRuleByIds(ids);
    }

    /**
     * 删除药品规则信息
     * 
     * @param id 药品规则ID
     * @return 结果
     */
    @Override
    public int deleteDrugRuleById(Long id)
    {
        return drugRuleMapper.deleteDrugRuleById(id);
    }


    @Override
    public Map<String,Object> verify(VerifyVo verify) {

        DrugRuleResolve query = new DrugRuleResolve();
        query.setDrugRuleId(verify.getDrugRuleId());
        List<DrugRuleResolve>  resolves = drugRuleResolveMapper.selectDrugRuleResolveList(query);

        DrugRule rule = drugRuleMapper.selectDrugRuleById(verify.getDrugRuleId());


        Expression expr = ExprParser.parse(rule.getExpression());

        Expression simplified = RuleSet.simplify(expr);

        Map<String,Boolean> map = new HashMap<>();
        Map<String,Object> feature = new HashMap<>();

        for(DrugRuleResolve resolve : resolves){
            DrugResolveTable drugResolveTable = new DrugResolveTable();
            drugResolveTable.setDrugRuleResolveId(resolve.getId());

            StringBuffer text = new StringBuffer();
            if(verify.getAdmissionId() != null) {
                List<DrugResolveTable> tables = drugResolveTableMapper.selectDrugResolveTableList(drugResolveTable);

                Map<String, List<DrugResolveTable>> groups = tables.stream().collect(Collectors.groupingBy(DrugResolveTable::getTableName));

                for (String key : groups.keySet()) {

                    List<String> columns = groups.get(key).stream().map(p -> p.getTableColumn()).collect(Collectors.toList());
                    //key 表名
                    // 字段名
                    String verifyText = drugRuleMapper.selectVerifyText(key, columns, verify.getAdmissionId());

                    text.append(verifyText).append(";");
                }
            }else{
                text.append(verify.getContent());
            }

            if("6".equals(resolve.getRuleCategory())){
                //正则取出语句
                //String pattern = resolve.getKeywords();
                Pattern r = Pattern.compile(resolve.getKeywords());
                Matcher m = r.matcher(text);
                if (m.find()){
                    //正则取数
                    String check = m.group();
                    Pattern r1 = Pattern.compile(resolve.getSemanteme());
                    Matcher m1 = r1.matcher(m.group());
                    if(m1.find()){
                        String checkValue = m1.group(1);
                        //处理科学计数法  293×10^9
                        BigDecimal result = null;
                        if(checkValue.indexOf("×") > 0){
                            BigDecimal first = new BigDecimal(checkValue.split("×")[0]);
                            BigDecimal second = new BigDecimal(checkValue.split("×")[1].replace("^","E"));
                            result = first.multiply(second);
                        }else{
                            result = new BigDecimal(checkValue);
                        }
                        BigDecimal targetValue = new BigDecimal(resolve.getTargetValue());
                        Boolean match = null;
                        switch (resolve.getMatchType()){
                            case "2":
                                //大于 >
                                match = result.compareTo(targetValue) == 1;
                                break;
                            case "3":
                                //等于 =
                                match = result.compareTo(targetValue) == 0;
                                break;
                            case "4":
                                //小于 <
                                match = result.compareTo(targetValue) == -1;
                                break;
                            case "5":
                                //大于等于 >=
                                match = result.compareTo(targetValue) > -1;
                                break;
                            case "6":
                                //小于等于 <=
                                match = result.compareTo(targetValue) < 1;
                        }
                        map.put(resolve.getCode(), match);
                        feature.put(resolve.getCode(),check);
                    }else{
                        System.err.println("未发现");
                        map.put(resolve.getCode(), false);
                        //feature.put(resolve.getCode(),check);
                    }
                }else{
                    map.put(resolve.getCode(), false);
                    //feature.put(resolve.getCode(),check);
                }
            }else if("5".equals(resolve.getRuleCategory())){ //字符
                //String url = "http://124.205.59.34:8002/match";
                MatchVo match = new MatchVo();

                match.setKeyword(Lists.newArrayList(resolve.getKeywords().split(",")));
                if(!"".equals(resolve.getSemanteme())) {
                    match.setSemanteme(Lists.newArrayList(resolve.getSemanteme().split(",")));
                }else{
                    match.setSemanteme(Lists.newArrayList());
                }
                match.setText(text.toString());
                match.setAlgorithmType("0");
                match.setMatchingMode(resolve.getMatchType());

                match.setModel(verify.getModel());
                try {
                    String result = HttpUtil.doPost(strMatchUrl, JSON.toJSON(match));
                    JSONObject json = JSON.parseObject(result);
                    map.put(resolve.getCode(), json.getBooleanValue("result"));

                    feature.put(resolve.getCode(),json.get("details"));
                }catch (Exception e){
                    e.printStackTrace();
                }
            }else{
                //bert 和其他模型
                //String url = "http://124.205.59.34:8001/match";
                MatchVo match = new MatchVo();

                match.setText(text.toString());
                match.setModel(resolve.getModelId());
                try {
                    String result = HttpUtil.doPost(aiMatchUrl, JSON.toJSON(match));
                    JSONObject json = JSON.parseObject(result);
                    map.put(resolve.getCode(), json.getBooleanValue("result"));
                    feature.put(resolve.getCode(),json.get("details"));
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }

        Expression halfAssigned = RuleSet.assign(
                simplified,
                map
        );
        JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(halfAssigned));

        //修改审核状态
        Boolean verifyResult = jsonObject.getBooleanValue("value");
        if(verify.getVerifyId() != null) {
            DrugVerify drugVerify = new DrugVerify();
            drugVerify.setId(verify.getVerifyId());
            drugVerify.setVerify(verifyResult ? 1 : 2);
            drugVerify.setVerifyTime(new Date());
            drugVerify.setRemark(JSON.toJSONString(map));
            //审核人 。
            drugVerifyService.updateDrugVerify(drugVerify);
        }

        Map<String,Object> resultMap = Maps.newHashMap();
        resultMap.put("result",verifyResult);
        resultMap.put("detail",map);
        resultMap.put("feature",feature);
        return resultMap;
    }

    @Override
    public DrugRule selectDrugRuleByDrugId(Long drugId) {
        return drugRuleMapper.selectDrugRuleByDrugId(drugId);
    }


    @Override
    public DrugRule verifyDetail(VerifyVo verify) {

        DrugRuleResolve query = new DrugRuleResolve();
        query.setDrugRuleId(verify.getDrugRuleId());
        List<DrugRuleResolve>  resolves = drugRuleResolveMapper.selectDrugRuleResolveList(query);

        DrugRule rule = drugRuleMapper.selectDrugRuleById(verify.getDrugRuleId());
        DrugVerify drugVerify = drugVerifyService.selectDrugVerifyById(verify.getVerifyId());
        StringBuffer content = new StringBuffer();
        for(DrugRuleResolve resolve : resolves){

            DrugResolveTable drugResolveTable = new DrugResolveTable();
            drugResolveTable.setDrugRuleResolveId(resolve.getId());

            StringBuffer text = new StringBuffer();
            List<DrugResolveTable> tables = drugResolveTableMapper.selectDrugResolveTableList(drugResolveTable);

            Map<String, List<DrugResolveTable>> groups = tables.stream().collect(Collectors.groupingBy(DrugResolveTable::getTableName));

            for (String key : groups.keySet()) {

                List<String> columns = groups.get(key).stream().map(p -> p.getTableColumn()).collect(Collectors.toList());
                //key 表名
                // 字段名
                String verifyText = drugRuleMapper.selectVerifyText(key, columns, verify.getAdmissionId());

                text.append(verifyText).append(";");
            }
            resolve.setContent(text.toString());

//            if(content.indexOf(text.toString()) != -1){
//                if(text.indexOf(content.toString()) != -1) {
//                    content.append(text);
//                }
//            }
            content.append(text);
        }
        rule.setResolves(resolves);
        rule.setVerifyInfo(drugVerify.getRemark());
        rule.setContent(content.toString());
        return rule;
    }

    @Override
    public Integer count() {
        return drugRuleMapper.count();
    }
}
